#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <sys/epoll.h>

class Epoller;
class EventLoop;

class Channel
{
private:
    int _fd;           // 文件描述符
    EventLoop* _ep;      // epoll对象指针
    uint32_t _events;  // 需要监控的事件
    uint32_t _revents; // 已经就绪的事件

    // 各种事件的回调函数
    using EventCallBack = std::function<void()>;
    EventCallBack _read_callback;  // 读事件回调函数
    EventCallBack _write_callback; // 写事件回调函数
    EventCallBack _error_callback; // 错误事件回调函数
    EventCallBack _close_callback; // 关闭事件回调函数
    EventCallBack _event_callback; // 任意事件回调函数

public:
    Channel(EventLoop* ep, int fd) :_fd(fd), _ep(ep) {}
    ~Channel();
    // 获取文件描述符
    int Fd() { return _fd; }
    //获取要监控的事件
    uint32_t Events() { return _events; }

    //设置已经就绪的事件
    void SetREvents(uint32_t revents) { _revents = revents; }
    // 设置各种事件回调函数
    void SetReadCallBack(const EventCallBack &cb) { _read_callback = cb; }
    void SetWriteCallBack(const EventCallBack &cb) { _write_callback = cb; }
    void SetErrorCallBack(const EventCallBack &cb) { _error_callback = cb; }
    void SetCloseCallBack(const EventCallBack &cb) { _close_callback = cb; }
    void SetEventCallBack(const EventCallBack &cb) { _event_callback = cb; }

    // 是否监控读事件
    bool ReadAble() { return _events & EPOLLIN; }
    // 是否监控写事件
    bool WriteAble() { return _events & EPOLLOUT; }
    // 开启读事件监控
    void EnableRead()
    {
        _events |= EPOLLIN;
        Update();
    }
    // 开启写事件监控
    void EnableWrite()
    {
        _events |= EPOLLOUT;
        Update();
    }
    // 关闭读事件监控
    void DisableRead()
    {
        _events &= ~EPOLLIN;
        Update();
    }
    // 关闭写事件监控
    void DisableWrite()
    {
        _events &= ~EPOLLOUT;
        Update();
    }
    // 关闭所有事件监控
    void DisableAll()
    {
        _events = 0;
        Remove();
    }

    // 更新事件监控
    void Update();
    // 移除事件监控
    void Remove();

    // 事件处理
    void HandleEvent()
    {
        // 读事件
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            if (_read_callback)
                _read_callback();
        }
        //对于可能会释放连接的操作，一次只处理一个
        // 写事件
        if (_revents & EPOLLOUT)
        {
            if (_write_callback)
                _write_callback();
        }
        // 错误事件
        else if (_revents & EPOLLERR)
        {
            if (_error_callback)
                _error_callback();
        }
        // 关闭连接事件
        else if (_revents & EPOLLHUP)
        {
            if (_close_callback)
                _close_callback();
        }
        // 任意事件
        if (_event_callback)
            _event_callback();
    }
};